﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package net.libra.loader.mission
{
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;
    import flash.utils.*;
    
    import net.libra.loader.*;
    import net.libra.loader.LoadEvent;
    import net.libra.loader.MD5;

    public class Mission extends EventDispatcher {

        public static var MAX_RETRY_COUNT:uint = 3;

        protected var sprite:Sprite;
        public var name:String;
        protected var clock:Timer;
        public var bytesLoaded:uint;
        public var base:String = "";
        protected var ldr:URLLoader;
        public var retryTime:uint = 0;
        protected var original:ByteArray;
        public var destroyed:Boolean;
        public var cacheType:uint;
        public var key:String;
        public var path:String;
        public var bytesTotal:uint;
        public var data:Object;
        public var applicationDomain:ApplicationDomain;
        public var useCache:Boolean;

        public function Mission(name:String, path:String, useCache:Boolean=true, cacheType:uint=1, key:String=null, data:Object=null){
            super();
            this.name = name;
            this.path = path;
            this.useCache = useCache;
            this.cacheType = cacheType;
            this.key = key;
            this.data = data;
        }
        public static function getKey(bytes:ByteArray):String{
            if (!(bytes)){
                return (null);
            };
            if (bytes.length < (0x0400 * 15)){
                return (MD5.hashBytes(bytes));
            };
            var byte:ByteArray = new ByteArray();
            bytes.position = 0;
            bytes.readBytes(byte, 0, (10 * 0x0400));
            bytes.position = (bytes.length - (5 * 0x0400));
            bytes.readBytes(byte, byte.length, 0);
            return (MD5.hashBytes(byte));
        }
        public static function copyBytes(bytes:ByteArray):ByteArray{
            if (!(bytes)){
                return (null);
            };
            var newBytes:ByteArray = new ByteArray();
            bytes.position = 0;
            bytes.readBytes(newBytes);
            return (newBytes);
        }

        protected function complete():void{
            if (!(sprite)){
                sprite = new Sprite();
                sprite.addEventListener(Event.ENTER_FRAME, frame);
            };
        }
        public function destroy():void{
            if (destroyed){
                return;
            };
            destroyed = true;
            applicationDomain = null;
            original = null;
            data = null;
            loaderAbort();
            if (ldr){
                ldr.removeEventListener(Event.COMPLETE, loaderHandler);
                ldr.removeEventListener(IOErrorEvent.IO_ERROR, loaderHandler);
                ldr.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, loaderHandler);
                ldr.removeEventListener(ProgressEvent.PROGRESS, loaderHandler);
                ldr = null;
                clock.reset();
                clock.removeEventListener(TimerEvent.TIMER_COMPLETE, timeOut);
                clock = null;
            };
            sprite.removeEventListener(Event.ENTER_FRAME, frame);
            sprite = null;
        }
        public function convert(source:ByteArray):void{
            if (destroyed){
                return;
            };
            original = source;
            complete();
        }
        public function start(bytes:ByteArray):void{
            if (destroyed){
                return;
            };
            retryTime = 0;
            dispatchEvent(new LoadEvent(LoadEvent.MISSION_START,null ,0, 0, this));
            dispatchEvent(new LoadEvent(LoadEvent.MISSION_PROGRESS,null, 0, 0, this));
            validate(bytes);
        }
        protected function error():void{
            loaderStart(false);
        }
        public function getClass(def:String):Class{
            var c:* = null;
            var def:* = def;
            if (destroyed){
                return (null);
            };
            try {
                c = (applicationDomain.getDefinition(def) as Class);
            } catch(error:Error) {
            };
            return (c);
        }
        protected function loaderStart(useCache:Boolean):void{
            loaderAbort();
            retryTime++;
            if (retryTime > MAX_RETRY_COUNT){
                dispatchEvent(new LoadEvent(LoadEvent.MISSION_ERROR,null ,0, 0, this));
                return;
            };
            if (!(ldr)){
                ldr = new URLLoader();
                ldr.addEventListener(Event.COMPLETE, loaderHandler);
                ldr.addEventListener(IOErrorEvent.IO_ERROR, loaderHandler);
                ldr.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loaderHandler);
                ldr.addEventListener(ProgressEvent.PROGRESS, loaderHandler);
                ldr.dataFormat = URLLoaderDataFormat.BINARY;
                clock = new Timer(1000, 1);
                clock.addEventListener(TimerEvent.TIMER_COMPLETE, timeOut);
            };
            if (retryTime == MAX_RETRY_COUNT){
                clock.delay = 5000;
            };
            if (useCache){
                ldr.load(new URLRequest((base + path)));
            } else {
                ldr.load(new URLRequest((((base + path) + "?") + new Date().getTime())));
            };
            clock.reset();
            clock.start();
        }
        protected function validate(bytes:ByteArray):void{
            var checkKey:String;
            if (!(bytes)){
                loaderStart(useCache);
                return;
            };
            if (key){
                checkKey = getKey(bytes);
                if (checkKey == key){
                    convert(bytes);
                } else {
                    trace("[CACHE]", "验证失败", name, "s=", key, "t=", checkKey);
                    loaderStart(false);
                };
            } else {
                convert(bytes);
            };
        }
        public function createObject(def:String):Object{
            var c:Class = getClass(def);
            return ((c) ? new (c)() : null);
        }
        protected function loaderAbort():void{
            if (ldr){
                clock.stop();
                try {
                    ldr.close();
                } catch(error:Error) {
                };
            };
        }
        public function get bytes():ByteArray{
            return (copyBytes(original));
        }
        override public function toString():String{
            return ((((((((((((((("[Mission(name=\"" + name) + "\",path=\"") + path) + "\",useCache=\"") + useCache) + "\",cacheType=\"") + cacheType) + "\",key=\"") + key) + "\",data=\"") + (data) ? "<object>" : "null") + "\",bytes=\"") + (original) ? "<object>" : "null") + "\")]"));
        }
        protected function frame(event:Event):void{
            sprite.removeEventListener(Event.ENTER_FRAME, frame);
            dispatchEvent(new LoadEvent(LoadEvent.MISSION_PROGRESS,null, bytes.length, bytes.length, this));
            dispatchEvent(new LoadEvent(LoadEvent.MISSION_COMPLETE,null, bytes.length, bytes.length, this));
        }
        protected function timeOut(event:TimerEvent):void{
            ldr.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "connect timeout"));
        }
        public function abort():void{
            if (destroyed){
                return;
            };
            if (sprite){
                sprite.removeEventListener(Event.ENTER_FRAME, frame);
            };
            loaderAbort();
            dispatchEvent(new LoadEvent(LoadEvent.MISSION_ABORT,null, 0, 0, this));
        }
        protected function loaderHandler(event:Event):void{
            var _local2:ProgressEvent;
            if (clock.running){
                clock.stop();
            };
            switch (event.type){
                case ProgressEvent.PROGRESS:
                    _local2 = (event as ProgressEvent);
                    bytesLoaded = _local2.bytesLoaded;
                    bytesTotal = _local2.bytesTotal;
                    dispatchEvent(new LoadEvent(LoadEvent.MISSION_PROGRESS,null, bytesLoaded, bytesTotal, this));
                    break;
                case Event.COMPLETE:
                    validate(ldr.data);
                    break;
                case IOErrorEvent.IO_ERROR:
                case SecurityErrorEvent.SECURITY_ERROR:
                    loaderStart(false);
                    break;
            };
        }

    }
}//package net.l4cd.loader.mission 
